#ifndef MULTIDIMENSIONAL_CONTAINER_HPP
#define MULTIDIMENSIONAL_CONTAINER_HPP

#include <concepts>
#include <memory>

namespace details
{

template <auto number>
concept is_greater_than_null = number > 0;

template <auto dimension>
concept is_dimensional = std::integral<decltype(dimension)> && is_greater_than_null<dimension>;

template <template <typename, typename> class Container, typename Value, auto dimension, template <typename> class Allocator>
    requires is_dimensional<dimension>
struct multidimensional_container;

template <template <typename> class Allocator, template <typename, typename> class Container, typename Value, auto dimension>
    requires is_dimensional<dimension>
struct multidimensional_allocator
{
    using container_type = typename multidimensional_container<Container, Value, dimension - 1, Allocator>::inner_type;
    using inner_type = Allocator<container_type>;
};

template <template <typename> class Allocator, template <typename, typename> class Container, typename Value>
struct multidimensional_allocator<Allocator, Container, Value, 1>
{
    using inner_type = Allocator<Value>;
};

template <template <typename, typename> class Container, typename Value, auto dimension, template <typename> class Allocator>
    requires is_dimensional<dimension>
struct multidimensional_container
{
    using allocator_type = typename multidimensional_allocator<Allocator, Container, Value, dimension>::inner_type;
    using inner_type = Container<typename multidimensional_container<Container, Value, dimension - 1, Allocator>::inner_type, allocator_type>;
};

template <template <typename, typename> class Container, typename Value, template <typename> class Allocator>
struct multidimensional_container<Container, Value, 1, Allocator>
{
    using inner_type = Container<Value, typename multidimensional_allocator<Allocator, Container, Value, 1>::inner_type>;
};

} // namespace details

template <template <typename, typename> class Container, typename Value, auto dimension, template <typename> class Allocator = std::allocator>
using multidimensional_container = typename details::multidimensional_container<Container, Value, dimension, Allocator>::inner_type;

#endif
